package com.HourlyDump;
import com.HourlyDump.HourlyData;

import org.hibernate.*; 
import org.hibernate.cfg.Configuration;

import java.io.*;

import org.apache.http.client.*;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import javax.xml.xpath.*;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import java.util.Date;
import java.text.DateFormat;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class YQLDump {

	/**
	 * @param args
	 * @throws IOException 
	 */
	static BufferedOutputStream Output_writer;
	static BufferedOutputStream Error_writer;
	static String config = new String();
	public static void SetLogger()
	{
		try {
			DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			Date date = new Date();
		
			
		
			Output_writer = new BufferedOutputStream(new FileOutputStream("output.log",true));
		
			System.setOut(new PrintStream(Output_writer));
			System.out.println();
			System.out.println("["+dateFormat.format(date)+"]");
			System.out.println();
			Error_writer = new BufferedOutputStream(new FileOutputStream("error.log",true));
			System.setErr(new PrintStream(Error_writer));
			System.err.println();
			System.err.println("["+dateFormat.format(date)+"]");
			System.err.println();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static int parse_file()
	{
		// I want to read the config file in one pass. So I append contents with a '+' to string 'config'
		//Then I separate the symbol names from '+' and write it to String array 'symbols'
		//Which is then used to fetch the historical data
		int n_symbols = 0;
		try {
		BufferedReader config_reader = new BufferedReader(new FileReader("config.dat"));
		String line;
		
		while ((line = config_reader.readLine()) != null)
		{
			n_symbols++;
			config = config.concat(line);
			config = config.concat("+");
		}
		
			config_reader.close();
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return n_symbols = -1;
		}
		return n_symbols;
	}	
	
	public static NodeList getNodes(String YQLQuery, HttpClient httpclient)
	{
		
		
		try {
			NodeList nodes;
		HttpGet httpget = new HttpGet(YQLQuery);
		HttpResponse response;
		response = httpclient.execute(httpget);
		
		HttpEntity entity = response.getEntity();
		
		InputStream instream = entity.getContent();
		
		/* This block is for debugging
		BufferedReader in = new BufferedReader(new InputStreamReader(instream));
		System.out.println(in.readLine());
		System.out.println(in.readLine());
		System.out.println(in.readLine());
		*/
		
		DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
	    domFactory.setNamespaceAware(true);
	    DocumentBuilder builder;
		
			builder = domFactory.newDocumentBuilder();
		
	    Document doc;
		doc = builder.parse(instream);
		

	    XPath xpath = XPathFactory.newInstance().newXPath();
	    XPathExpression expr;
		
	    expr = xpath.compile("//quote/*/text()");
		
	    nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
	    return nodes;
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		 return null;			
		
	    
	}
	

	public static void main(String[] args) throws IOException {
		
		/*
		 * Grabbed Majority of code for getting XML from Apache Documentation :-|
		 * Implementation is pretty standard. I pass a request. I get a response and every response has an entity - which is the XML file we need :-)
		 * So next I store the content within entity into an InputStrem object - which can handle data at byte level.
		 * After getting the XML into inputstream object I use XPath to traverse the nodes of XML file. In this file I print all the text within quote --> Ask. Tree goes like this.
		 */
		
	
		
		try 
		{
			
			/* Redirecting all output to log files error.log and output.log */
			YQLDump.SetLogger();
		
			
			
			/* Enable this if you want data dump to file data.dat
			BufferedWriter stock_writer = new BufferedWriter(new FileWriter("data.dat"));
			*/
			
			//Read config file to get list of symbols.
			int n_symbols = YQLDump.parse_file();
			String[] symbols = new String[n_symbols];
			
			int cursor = 0;
			int curr_symbol = 0;
			while((cursor<=(config.length())-1))
			{
				symbols[curr_symbol++] = config.substring(cursor,config.indexOf("+",cursor));
				cursor = config.indexOf("+",cursor) + 1;
			}
			
			/*Get the start and end date into strings to build the query*/
			Calendar my_calendar = Calendar.getInstance();
			String current_date = new String(new SimpleDateFormat("yyyy-dd-MM").format(my_calendar.getTime()));
			DateFormat dateFormat_time = new SimpleDateFormat("HH:mm:ss");
	        Date time = new Date();
	        System.out.println("Time:"+dateFormat_time.format(time));
			
			HttpClient httpclient = new DefaultHttpClient();
	        
	        for(int j = 0; j<n_symbols;j++)
	        {
	        	String YQLQuery = new String("http://query.yahooapis.com/v1/public/yql?q=select%20Ask,Bid%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22"+symbols[j]+"%22)&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys");
	        	System.out.println("URL:\n["+YQLQuery+"\n]");
	        	HttpGet httpget = new HttpGet(YQLQuery);
				
			    NodeList nodes = YQLDump.getNodes(YQLQuery, httpclient);
			    System.out.println("Fetched "+nodes.getLength()+" nodes.");
		        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); 
		        Session session =sessionFactory.openSession();
		        int samp = 0;
		        
		        if(nodes.getLength() != 0)
		        {
		        	
		        	for (int i = 0; i < nodes.getLength(); i=i+7) {
			    	HourlyData user1 = new HourlyData(); 
			    	
			    	user1.setsymbol(symbols[j]);		    
			    	user1.setdate(current_date);
			    	user1.settime(dateFormat_time.format(time));
			        user1.setask(Double.parseDouble(nodes.item(i).getNodeValue()));
			        user1.setbid(Double.parseDouble(nodes.item(i+1).getNodeValue()));
			    	session.save(user1);
			    
			        session.flush();
			        
			    	
			    	/*Enable this if you want data dump into a file data.dat 
			    	if(samp==10)
			    	{
			    		stock_writer.write(nodes.item(i+2).getNodeValue());
			    		stock_writer.newLine();
			    		samp=0;
			    	}				    	
			    	else
			    	{
			    		stock_writer.write(nodes.item(i+2).getNodeValue()+",");
			    		samp++;
			    	}
			    	*/
			    }
			    System.out.println("Data written:" + symbols[j]);
		      }
		        else
		        	System.out.println("Update Failed. Retaining old data!!");
				        
			
			
	        }
	        /* Enable this if you want dump to file config.dat
	         * stock_writer.close();
	         */
	        Output_writer.close();
	        Error_writer.close();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} 
	}

}
